﻿using System;

using Unity.Interception.PolicyInjection.Pipeline;

using pri.smilly.QuickStart;
using pri.smilly.QuickStart.Aop;
using pri.smilly.QuickStart.Ioc;
using pri.smilly.QuickStart.Config;

namespace pri.smilly.boot {
    /// <summary>
    /// 通过 Aspect 标记拦截的方法，并且通过 BeforeHandle 指定处理方法
    /// </summary>
    [Aspect(Expression = "pri.smilly.boot.*.*(..)", Order = 0)]
    public class LoggingHandler {

        [BeforeHandle]
        public void Before(IMethodInvocation input) {
            Console.WriteLine($"before method {input.MethodBase.Name} executing");
        }

        [AfterHandle]
        public void After(IMethodInvocation input, IMethodReturn result) {
            Console.WriteLine($"after method {input.MethodBase.Name} executed, result value : {result.ReturnValue}");
        }

        [ExceptHandle]
        public void Exception(IMethodInvocation input, Exception except) {
            Console.WriteLine($"method {input.MethodBase.Name} execute whith error : {except.Message}");
        }

        [FinallyHandle]
        public void Finally(IMethodInvocation input) {
            Console.WriteLine($"method {input.MethodBase.Name} execution finalize");
        }
    }

    /// <summary>
    /// 通过 Configurator 的方式注入
    /// </summary>
    [Configurator]
    public class BeanConfiguration {
        [Bean(Type = typeof(IPrinter))]
        public IPrinter Printer() {
            return new Printer();
        }
    }

    public interface IPrinter {
        void Print();
    }

    public class Printer : IPrinter {
        public void Print() {
            Console.WriteLine("Printer method Print executing...");
        }
    }

    /// <summary>
    /// 通过 PointCut 标注需要拦截的类
    /// </summary>
    [PointCut]
    public interface IStudent {
        void Show();
    }

    /// <summary>
    /// 通过 Bean 标注类名自动注入
    /// </summary>
    [Bean(Type = typeof(IStudent), LifeTime = LifeTime.Singleton)]
    public class Student : IStudent {
        public void Show() {
            Console.WriteLine("Student method Show executing...");
            throw new Exception("Student method Show execute error");
        }
    }

    class Program {
        static void Main(string[] args) {
            ApplicationContext.Initialize();
            ApplicationContext.GetBean<IPrinter>().Print();
            ApplicationContext.GetBean<IStudent>().Show();
        }
    }
}
